package entity;

import java.util.ArrayList;

/**
 * An entity exist in a world.
 * 
 * An entity has a series of module that implement the different
 * functionalities this entity will have. A module is also an entity.
 * 
 * An entity can only have 1 module of each sort. You add module to an entity
 * not to represent the data of this entity but to add functionality to this
 * entity.
 * 
 * Example : You have a character in a RPG that has many items. Trying to
 * add each item to the character as an entity would be a bad idea. The good
 * way to do it would be to add an InventoryEntity to the character and then
 * that inventory could hold a reference to every item the player have.
 * 
 * ----------------------------------------------------------------------------
 * 
 * Why should you use entity in your game?
 * 
 * 1. It enables you to work in team! That is probably the biggest advantage.
 * Imagine you have the character with his inventory and that character can
 * also attack enemies. You can easily create a sort of inventory and the code 
 * to attack the enemies inside the Character class. Now what if, you and your
 * friend want to work at the same time on the code for the inventory and on 
 * the code for attacking enemies. If you put everything in the same class you
 * could get a lot of problem with merging both of your part later on. By
 * splitting the logic in module you can both work on the same entity at the 
 * same time.
 * 
 * 2. The code can be reuse more easily! Since you split everything in small
 * bit of logic, there is a lot more chance that you could reuse your code in
 * an other part of the project or in an other project.
 * 
 * 3. Greatly reduce the size of the classes! Everything is split up in small
 * module so you don't have gigantic class with lot of functionalities.
 * 
 * 4. Make refactoring a lot easier! Since you split up everything in small
 * chunk you can't produce code that are interrelated between itself and that
 * are practically impossible to refactor. I'm sure everyone has already done
 * it many times. You create a class with many functionalities and everything
 * in the class is interrelated. Then you want to change/remove/add a 
 * functionalities but it is so hard to change that class because everything is
 * interrelated inside it and as soon as you make a small change the rest break
 * up. Well, that's something you want to avoid. Code that can't be change is
 * bad code.
 * 
 * 5. Give easy access to everything in the world! Writing the code to store
 * and access thing in your game is probably the most boring one to do. Since 
 * every entity has a connection to the world and the world has a connection to
 * every entity in it, it's always easy to get the information you want at any
 * time.
 * 
 * @author Gudradain
 *
 */
public class Entity {
	
	private final ArrayList<Entity> entityList = new ArrayList<Entity>();
	
	private final World world;
	private final ParameterMap parameterMap = new ParameterMap();
	
	public Entity(World world, ParameterMap parameterMap){
		this.world = world;
		setParameterMap(parameterMap);
	}
	
	/**
	 * Set all the attributes of this entity.
	 * 
	 * @param parameterMap
	 */
	public void setParameterMap(ParameterMap parameterMap){
		//this.parameterMap.setString("example", parameterMap.getString("example"))
	}
	
	/**
	 * The list of all attributes of this entity
	 * 
	 * @return
	 */
	public ParameterMap getParameterMap(){
		return parameterMap.clone();
	}
	
	/**
	 * The world in which this entity exist
	 * 
	 * @return
	 */
	public World getWorld(){
		return world;
	}
	
	/**
	 * The unique ID of this sort of entity.
	 * 
	 * @return
	 */
	public String getID(){
		return getClass().getName();
	}
	
	/**
	 * Add an entity to this one. 
	 * 
	 * An entity can only have 1 entity of each sort. If you try to add more
	 * than one entity of the same sort it will throw an exception.
	 * 
	 * @param entity
	 * @throws Exception 
	 */
	public void addModule(Entity entity) throws Exception{
		for(Entity e : entityList){
			if(e.getID().equals(entity.getID())){
				throw new Exception("This entity already have an entity of this sort");
			}
		}
		entityList.add(entity);
	}
	
	/**
	 * Remove an entity
	 * 
	 * @param entity
	 */
	public void removeModule(Entity entity){
		entityList.remove(entity);
	}
	
	/**
	 * Get all the entities related to this one
	 * 
	 * @return
	 */
	public ArrayList<Entity> getModuleList(){
		ArrayList<Entity> newEntityList = new ArrayList<Entity>();
		for(Entity entity : entityList){
			newEntityList.add(entity);
		}
		return newEntityList;
	}
	
	/**
	 * Get the entity of this sort
	 * 
	 * @param entityID
	 * @return
	 */
	public Entity getModule(String entityID){
		Entity newEntity = null;
		for(Entity entity : entityList){
			if(entity.getID().equals(entityID)){
				newEntity = entity;
				break;
			}
		}
		return newEntity;
	}

}
